/*
 * Copyright 2018 peipeihh
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * limitations under the License.
 */

package com.pphh.demo;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by huangyinhuang on 3/15/2018.
 */
public class CookieUtils {

    static private String defaultDomain = "localhost";
    static private String defaultPath = "/";
    static private boolean defaultSecure = false;
    static private int defaultExpiry = 3600;

    /**
     * Print out the cookies from incoming request
     *
     * @param request the incoming request
     */
    static public void printCookies(HttpServletRequest request) {

        Cookie[] cookies = request.getCookies();
        if (null == cookies) {
            System.out.println("No cookie.");
        } else {
            System.out.println("print cookies on the request...");
            int count = 0;
            for (Cookie cookie : cookies) {
                System.out.println(String.format("cookies[%s] name = %s, value = %s",
                        ++count, cookie.getName(), cookie.getValue()));
            }
        }

    }

    /**
     * set a cookie with default settings
     *
     * @param response the response to be send to user
     * @param name     cookie's name
     * @param value    cookie's value
     */
    static public void setCookie(HttpServletResponse response, String name, String value) {
        setCookie(response, name, value, defaultDomain, defaultPath, defaultSecure, defaultExpiry);
    }


    /**
     * set a cookie
     *
     * @param response the response to be send to user
     * @param name     cookie's name
     * @param value    cookie's value
     * @param domain   cookie's domain
     * @param path     cookie's path
     * @param isSecure is cookie for https only
     * @param expiry   cookie's expiration time (second)
     */
    static public void setCookie(HttpServletResponse response, String name, String value,
                                 String domain, String path, boolean isSecure, int expiry) {
        Cookie cookie = new Cookie(name.trim(), value.trim());
        cookie.setDomain(domain);
        cookie.setPath(path);
        cookie.setMaxAge(expiry);
        cookie.setSecure(isSecure);

        System.out.println(String.format("add a cookie, name = %s, value = %s", cookie.getName(), cookie.getValue()));
        response.addCookie(cookie);
    }

    /**
     * edit a cookie's value
     *
     * @param request  the incoming request
     * @param response the output response to be send to user
     * @param name     cookie's name
     * @param value    cookie's value
     * @return return a boolean value, which indicate if the cookies has been edited.
     */
    static public boolean editCookie(HttpServletRequest request, HttpServletResponse response, String name, String value) {
        boolean bHasEdited = false;
        Cookie[] cookies = request.getCookies();
        if (null != cookies) {
            for (Cookie cookie : cookies) {
                if (cookie.getName().equals(name)) {
                    System.out.println("cookie name:" + cookie.getName());
                    System.out.println("cookie original value:" + cookie.getValue());
                    System.out.println("cookie new value:" + value);

                    response.addCookie(cookie);
                    bHasEdited = true;
                    break;
                }
            }
        }

        return bHasEdited;

    }

    /**
     * remove a cookie from response
     *
     * @param request  the incoming request
     * @param response the output response to be send to user
     * @param name     cookie's name
     * @return return a boolean value, which indicate if the cookies has been edited.
     */
    static public boolean removeCookie(HttpServletRequest request, HttpServletResponse response, String name) {
        boolean bHasEdited = false;

        Cookie[] cookies = request.getCookies();
        if (null == cookies) {
            System.out.println("No cookie.");
        } else {
            for (Cookie cookie : cookies) {
                if (cookie.getName().equals(name)) {
                    cookie.setValue(null);
                    cookie.setMaxAge(0); // remove the cookie by setting the max age as 0 seconds
                    cookie.setPath("/");
                    System.out.println("Cookie is removed:" + cookie.getName());
                    response.addCookie(cookie);
                    bHasEdited = true;
                    break;
                }
            }
        }

        return bHasEdited;
    }

    /**
     * read the cookie by name
     *
     * @param request the incoming request
     * @param name    cookie's name
     * @return the cookie by name, or null if not found
     */
    static public Cookie getCookieByName(HttpServletRequest request, String name) {
        Map<String, Cookie> cookieMap = readCookieMap(request);
        if (cookieMap.containsKey(name)) {
            Cookie cookie = (Cookie) cookieMap.get(name);
            return cookie;
        } else {
            return null;
        }
    }

    /**
     * return the list of cookies by the request
     *
     * @param request the incoming request
     * @return a map of cookies
     */
    static public Map<String, Cookie> readCookieMap(HttpServletRequest request) {
        Map<String, Cookie> cookieMap = new HashMap<String, Cookie>();
        Cookie[] cookies = request.getCookies();
        if (null != cookies) {
            for (Cookie cookie : cookies) {
                cookieMap.put(cookie.getName(), cookie);
            }
        }
        return cookieMap;
    }
}
